
(* A small compiler for a small language *)

type nmtoken = string

type expr =
	| EVar of nmtoken
	| ENum of int
	| EConstr of int * int
	| EAp of expr * expr
	| ELet of bool * (nmtoken * expr) list * expr
	| ECase of expr * alter list
	| ELam of nmtoken list * expr
and alter = int * nmtoken list * expr

type program = scdefn list

and scdefn = nmtoken * nmtoken list * expr

let var v = EVar v
let num n = ENum n
let constr tag arity = EConstr (tag, arity)
let ap f x = EAp (f, x)
let case e l = ECase (e, l)
let lam l e = ELam (l, e)
let alter n l e = (n, l, e)

(*
	I x = x
	K  x y = x
	K1 x y = y
	S f g x = f x (g x)
	compose f g x = f (g x)
	twice f = compose f f
*)
let prelude : program = [
		"I", ["x"], var "x";
		"K", ["x"; "y"], var "x";
		"K1", ["x"; "y"], var "y";
		"S", ["f"; "g"; "x"], ap (ap (var "f") (var "x")) (ap (var "g") (var "x"));
		"compose", ["f"; "g"; "x"], ap (var "f") (ap (var "g") (var "x"));
		"twice", ["f"], ap (ap (var "compose") (var "f")) (var "f")
	]
